package com.bluegalaxy.nhb.snapi.controller.api.ck;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bluegalaxy.nhb.service.AnalyseSqlService;
import com.bluegalaxy.nhb.snapi.core.common.OvervivwUtil;
import com.bluegalaxy.nhb.snapi.core.common.UntisCom;
import com.bluegalaxy.nhb.snservice.common.utils.DateUtil;
import com.bluegalaxy.nhb.snservice.core.util.NumberUtil;
import com.bluegalaxy.nhb.snservice.domain.constant.AppConstant;
import com.bluegalaxy.nhb.snservice.domain.constant.CkConstant;
import com.bluegalaxy.nhb.snservice.domain.vo.api.R;
import com.bluegalaxy.nhb.snservice.domain.vo.api.ck.*;
import com.bluegalaxy.nhb.snservice.service.ck.FunnelService;
import com.bluegalaxy.nhb.snservice.service.ck.SpreadService;
import com.bluegalaxy.nhb.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.bluegalaxy.nhb.snservice.domain.constant.CkConstant.m_funnel;
import static com.bluegalaxy.nhb.snservice.domain.constant.CkConstant.queryItems;

/**
 * 分布分析
 */
@RestController
@RequestMapping(AppConstant.APPLICATION_NAME+"/spread")
@Api(value = "分布分析", tags = "分布分析API")
public class SpreadController {
    private static Log log = LogFactory.getLog(SpreadController.class);

    @Autowired
    private SpreadService spreadService;
    @Resource
    private AnalyseSqlService sqlService;


    @ResponseBody
    @PostMapping("/findSpread")
    @ApiOperation(value = "查询分布分析", notes = "查询分布分析列表")
    public R findSpread(@RequestBody SpreadReq paramVO) {
        log.info("findSpread param参数："+JSONObject.toJSONString(paramVO));

        List<OverviewItemReq> itemList = paramVO.getEventItemList();

        String sSql = UntisCom.beforeFloatWhere(null,paramVO.getFieldName());
        if ("Y".equals(paramVO.getIsInt())){
            sSql = UntisCom.beforeWhere(paramVO.getMethodName(),paramVO.getFieldName());
        }
        if (StringUtil.isEmpty(paramVO.getFieldName())){
            sSql = UntisCom.beforeWhere(paramVO.getMethodName());
        }
        String  methodName= paramVO.getMethodName()==null?"":paramVO.getMethodName();

        paramVO.setsSql(sSql);
        if (CkConstant.ct_virtual.equals(paramVO.getCategoryType())){
            paramVO.setEventValue(getVirtualEventValue(paramVO.getJsonParam()));
            paramVO.setwSql(getVirtualSql(paramVO.getJsonParam()));
        }else{
            paramVO.setEventValue(paramVO.getEventName());
            paramVO.setwSql(sqlService.analyseSql(paramVO.getJsonParam(), CkConstant.m_spread,CkConstant.initRuleTypes));
        }
//        paramVO.setwSql(sqlService.analyseSql(paramVO.getJsonParam(), CkConstant.m_spread,CkConstant.initRuleTypes));
        paramVO.setConditionSql(sqlService.analyseSql(paramVO.getJsonParam(), CkConstant.m_spread,CkConstant.userAttributes));

        if (StringUtil.isEmpty(paramVO.getGroupBy())){
            paramVO.setGroupBy("time");
        }
        paramVO.setgSql(UntisCom.getGroupBySql(paramVO.getGroupBy()));
//        paramVO.setGroupBy(" groupField ");
//        List<String> dateList= DateUtil.getBetweenDates(paramVO.getStartDate(),paramVO.getEndDate());
        List<SpreadVO> spreadList = spreadService.findSpreadList(paramVO);
        List<SpreadVO> resList = new ArrayList<>();
        if (spreadList != null && spreadList.size() > 0){
            String maxCountStr = spreadList.get(0).getEventCount();
            int maxCount = NumberUtil.dealNumber(Integer.parseInt(maxCountStr));
            Map<String,List<SpreadVO>> mapList = spreadList.stream().collect(
                    Collectors.groupingBy(a -> a.getEventGroup()));

            for (Map.Entry<String, List<SpreadVO>> m : mapList.entrySet()) {

                String eventGroup = m.getKey();
                List<SpreadVO> spreadVOList = m.getValue();

//                int sumCount = spreadVOList.stream().map(e -> Integer.parseInt(e.getEventCount())).reduce(0, (a,b) -> a + b);

                SpreadVO res = new SpreadVO();
                res.setTotal(spreadList.size());
                res.setEventGroup(eventGroup);
                res.setEventDate(eventGroup);
                if (methodName.contains("count") || (StringUtil.isEmpty(paramVO.getFieldName()) && methodName.contains("sum"))
                        ||(StringUtil.isEmpty(paramVO.getFieldName()) && methodName.contains("avg"))){
                    res.setEventCount(spreadVOList.size()+"");
//                    res.setTotal(spreadList.size());
                }else{
//                    res.setTotal(spreadList.size());
                    res.setDetailVOList(getEventCount(spreadVOList,maxCount));
                }
                resList.add(res);
            }
        }

        return R.data(resList);
    }

    private List<SpreadDetailVO> getEventCount(List<SpreadVO> spreadVOList,int maxCount){
        List<SpreadDetailVO> detailVOList = new ArrayList<>();
        int size = maxCount;
        int count = 5;
        int length = maxCount/count;
        for (int i = 0; i < count; i++) {
            SpreadDetailVO detailVO = new SpreadDetailVO();
            detailVO.setMinCount(i * length);
            detailVO.setMaxCount(((length + i * length) < size ? (length + i * length) : size));
            detailVO.setTitle((detailVO.getMinCount())+"-"+detailVO.getMaxCount());
            detailVO.setTitleValue(BigDecimal.ZERO);
            detailVOList.add(detailVO);
        }

        for (SpreadVO vo : spreadVOList){
            setDetailValue(vo,detailVOList);
        }

        return detailVOList;
    }

    private void setDetailValue(SpreadVO vo,List<SpreadDetailVO> detailVOList){
        Integer eventCount = StringUtil.isEmpty(vo.getEventCount())?0:Integer.parseInt(vo.getEventCount());
        for (SpreadDetailVO detailVO : detailVOList){
            if (eventCount > detailVO.getMinCount() && eventCount <= detailVO.getMaxCount()){
                detailVO.setTitleValue(detailVO.getTitleValue().add(BigDecimal.ONE));
            }
        }
    }

    private String getVirtualSql(JSONObject virtualParam){
        StringBuffer virtualSqls = new StringBuffer();
        if (virtualParam.containsKey("eventJson")){
            JSONArray jsonArray = virtualParam.getJSONArray("eventJson");
            for(int i=0;i<jsonArray.size();i++){
                JSONObject jsonParam = jsonArray.getJSONObject(i);
                virtualSqls.append(sqlService.analyseSql(jsonParam, CkConstant.m_spread,CkConstant.initRuleTypes));
            }

        }

        return virtualSqls.toString();
    }

    private String getVirtualEventValue(JSONObject virtualParam){
        StringBuffer values = new StringBuffer();
        if (virtualParam.containsKey("eventJson")){
            JSONArray jsonArray = virtualParam.getJSONArray("eventJson");
            for(int i=0;i<jsonArray.size();i++){
                JSONObject jsonParam = jsonArray.getJSONObject(i);
                if (i != 0){
                    values.append(",");
                }
                values.append("'");
                values.append(jsonParam.getString("eventType"));
                values.append("'");
            }

        }

        return values.toString();
    }


}
